#include "bsp_i2c_gpio.h"
#include "gpio.h"

// #define USING_STM32
#define USING_F1C200S

// pd12 scl
// pd0  sda

// 103c8t6 PB6-SCL    PB7-SDA
#ifndef __IO
#define __IO volatile
#endif

void SDA_OUT();
void SDA_IN();

#ifdef USING_STM32
#include "stm32f1xx_ll_gpio.h"
#define sda_gpio_port GPIOB
#define sda_pin GPIO_PIN_7

#define scl_gpio_port GPIOB
#define scl_pin GPIO_PIN_6

#define SDA(X) HAL_GPIO_WritePin(sda_gpio_port, sda_pin, (GPIO_PinState)X)
#define SCL(X) HAL_GPIO_WritePin(scl_gpio_port, scl_pin, (GPIO_PinState)X)
#define SDA_STATE (sda_gpio_port->IDR & sda_pin)

void i2c_gpio_init()
{
     GPIO_InitTypeDef GPIO_InitStruct = {0};

     /* GPIO Ports Clock Enable */
     __HAL_RCC_GPIOB_CLK_ENABLE();

     /*Configure GPIO pin Output Level */
     HAL_GPIO_WritePin(sda_gpio_port, sda_pin, GPIO_PIN_SET);
     HAL_GPIO_WritePin(scl_gpio_port, scl_pin, GPIO_PIN_SET);

     /*Configure GPIO pins : PBPin PBPin */
     GPIO_InitStruct.Pin = sda_pin | scl_pin;
     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 开漏输出
     GPIO_InitStruct.Pull = GPIO_PULLUP;
     GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

inline void SDA_OUT()
{
     LL_GPIO_SetPinMode(GPIOB, sda_pin, LL_GPIO_MODE_OUTPUT); // LL库
}

inline void SDA_IN()
{
     LL_GPIO_SetPinMode(GPIOB, sda_pin, LL_GPIO_MODE_INPUT); // LL库
}

void i2c_delay1us()
{
     __IO int i = 0;
     for (i = 0; i < 3; i++) // 72mHZ 大约2us
     {
          asm("nop");
     }
}

#endif

#ifdef USING_F1C200S
#include "time0.h"
#include "stdio.h"
#define HAL_Delay delay
#define scl_pin 12
#define scl_gpio_port GPIOD

#define sda_pin 0
#define sda_gpio_port GPIOD
#define SDA_STATE (gpio_pin_get(sda_gpio_port, sda_pin))

void SDA(uint8_t stat)
{
     if (stat)
     {
          GPIOD_PORT->DATA |= (1 << sda_pin);
     }
     else
     {
          GPIOD_PORT->DATA &= ~(1 << sda_pin); // SDA SCL SET 1
     }
}

void SCL(uint8_t stat)
{

     if (stat)
     {
          GPIOD_PORT->DATA |= (1 << scl_pin);
     }
     else
     {
          GPIOD_PORT->DATA &= ~(1 << scl_pin); // SDA SCL SET 1
     }
}

void i2c_gpio_init()
{
     printf("twi0 gpio mode init.\r\n");
     GPIOD_PORT->DATA |= ((1 << scl_pin) | (1 << sda_pin)); // SDA SCL SET 1

     GPIOD_PORT->CFG1 &= ~((0x07 << ((scl_pin % 8) * 4)));
     GPIOD_PORT->CFG1 |= ((0x01 << ((scl_pin % 8) * 4))); // 0-input  1-output 6-EINT

     GPIOE_PORT->PUL0 &= ~(0X03 << (scl_pin * 2)); // 0 NO PULL
     GPIOE_PORT->PUL0 |= (0X00 << (scl_pin * 2));  // pull up

     GPIOD_PORT->CFG0 &= ~((0x07 << ((sda_pin % 8) * 4)));
     GPIOD_PORT->CFG0 |= ((0x01 << ((sda_pin % 8) * 4))); // 0-input  1-output 6-EINT

     GPIOE_PORT->PUL0 &= ~(0X03 << (sda_pin * 2)); // 0 NO PULL
     GPIOE_PORT->PUL0 |= (0X00 << (sda_pin * 2));  // 0 PULL UP DOWN DISABLE  1 PULLUP  2 PULLDOWN  3 RESERVED
}

inline void SDA_OUT()
{
     // GPIOD_PORT->CFG0 &= ~((0x07 << ((sda_pin % 8) * 4))); SDA IN 的时候清0了
     GPIOD_PORT->CFG0 |= ((0x01 << ((sda_pin % 8) * 4))); // 0-input  1-output 6-EINT
}

inline void SDA_IN()
{
     GPIOD_PORT->CFG0 &= ~((0x07 << ((sda_pin % 8) * 4))); // 0-input  1-output 6-EINT
}

void i2c_delay1us()
{
     __IO int i = 0;
     for (i = 0; i < 40; i++)
     {
          asm("nop");
     }
}

#endif

void static i2c_delay()
{
     i2c_delay1us();
     i2c_delay1us();
}

void i2c_delay_us(uint16_t us)
{
     int z = 0;
     for (z = 0; z < us; z++)
     {
          i2c_delay1us();
     }
}

// scl 1-0 sda 1-0
//  在SCL=1 SDA=1  DELAY(可选）   SDA 拉低 DELAY(可选）     最简单 SCL =1 SDA=1 SDA =0
void i2c_start()
{
     SDA(1);
     SCL(1);
     SDA_OUT();

     i2c_delay1us();
     SDA(0);
     i2c_delay1us();
}

// start : scl 1 sda 0
//  scl =0 chang SCL   scl 0->1 slave read SDA
void i2c_write_byte(uint8_t data) //
{
     uint8_t i = 0;
     uint8_t temp = data;
     SCL(0);
     i2c_delay1us();
     SDA(((temp & 0x80) >> 7));
     SDA_OUT();
     for (i = 0; i < 8; i++)
     {
          SDA(((temp & 0x80) >> 7)); // MSB first
          i2c_delay1us();

          SCL(1);
          i2c_delay();

          temp <<= 1;

          SCL(0);
          i2c_delay1us();
     }
}
// 发送完数据 SCL 0   scl 1-0 sda wait 0
uint8_t i2c_wait_ack()
{
     uint16_t err = 0;
     SDA_IN();
     i2c_delay1us();

     SCL(1);
     i2c_delay1us();
     while (SDA_STATE)
     {
          err++;
          if (err > 6000)
          {
               i2c_stop();
               // printf("i2c wait_ack err0.\r\n");
               return 1;
          }
     }
     SCL(0); // SDA 释放 默认上拉
     return 0;
}

// scl 0->1 sda 0->1
// SDA 必须在SCL=0是 拉低 ， 必须在SCL=1的时候拉高  顺序  [ SCL=0 SDA=0  DELAY(可选）   SCL=1 DELAY(可选） SDA=1 ]  最终 SCL=1 SDA=1
void i2c_stop()
{
     SCL(0);
     asm("nop");
     asm("nop");
     SDA(0);
     SDA_OUT();
     i2c_delay1us();

     SCL(1);
     i2c_delay1us();

     SDA(1);
     i2c_delay1us();
}

// SCL 0-1-0  SDA 0
void i2c_ack()
{
     SCL(0);
     asm("nop");
     asm("nop");

     SDA(0);
     SDA_OUT();
     i2c_delay1us();

     SCL(1);
     i2c_delay();

     SCL(0);
     i2c_delay();
}

// SCL 0-1-0  SDA 1
void i2c_nack()
{
     SCL(0);
     asm("nop");
     asm("nop");

     SDA(1);
     SDA_OUT();
     i2c_delay1us();

     SCL(1);
     i2c_delay();

     SCL(0);
     i2c_delay();
}

uint8_t i2c_get_byte(uint8_t ack)
{
     uint8_t data = 0, i = 0;
     SDA_IN();
     for (i = 0; i < 8; i++)
     {
          SCL(0);
          i2c_delay();

          SCL(1);
          data <<= 1;
          if (SDA_STATE)
          {
               data++;
          }
          i2c_delay();
     }
     if (ack)
     {
          i2c_ack();
     }
     else
     {
          i2c_nack();
     }
     return data;
}

void i2c_write_mem_16bit(uint8_t driver_addr, uint16_t memaddr, uint8_t *buf, uint16_t len)
{
}

void i2c_24c02_write_mem_8bit(uint16_t memaddr, uint8_t buf)
{

     i2c_start();
     i2c_write_byte(0XA0 + ((memaddr / 256) << 1));
     ; // 24c02 0xa0+memaddr/256<<1 高地址
     i2c_wait_ack();
     i2c_write_byte(memaddr % 256);
     i2c_wait_ack();
     i2c_write_byte(buf);
     i2c_wait_ack();
     i2c_stop();
     HAL_Delay(3); // 写一个字节 需要3ms
     // i2c_delay_us(200);
}

void i2c_24c02_write_mem_8bit_256(uint16_t memaddr, uint8_t buf)
{
     i2c_start();
     i2c_write_byte(0xa0 + ((memaddr / 256) << 1)); // 24c02 0xa0+memaddr/256<<1 高地址
     i2c_wait_ack();
     i2c_write_byte(memaddr % 256);
     i2c_wait_ack();

     i2c_write_byte(buf);
     i2c_wait_ack();
     i2c_stop();
     // i2c_delay_us(200);
     HAL_Delay(5);
}

// 测试OK
uint8_t i2c_24c02_read_mem_8bit(uint16_t memaddr)
{
     uint8_t data = 0;

     i2c_start();
     i2c_write_byte(0xa0 + ((memaddr / 256) << 1)); // 24c02 0xa0+memaddr/256<<1 高地址
     i2c_wait_ack();
     i2c_write_byte(memaddr % 256);
     i2c_wait_ack();

     i2c_start();
     i2c_write_byte(0xa1);
     i2c_wait_ack();
     data = i2c_get_byte(0);
     i2c_stop();
     return data;
}

// 测试OK
uint8_t i2c_24c02_read_mem(uint16_t memaddr, uint8_t *buf, uint8_t len)
{
     uint8_t data = 0;

     i2c_start();
     i2c_write_byte(0xa0 + ((memaddr / 256) << 1)); // 24c02 0xa0+memaddr/256<<1 高地址
     i2c_wait_ack();
     i2c_write_byte(memaddr % 256);
     i2c_wait_ack();

     i2c_start();
     i2c_write_byte(0xa1);
     i2c_wait_ack();

     int i = 0;
     for (i = 0; i < (len - 1); i++)
     {
          buf[i] = i2c_get_byte(1);
     }
     buf[i] = i2c_get_byte(0);

     i2c_stop();
     return data;
}

// 在AT24CXX里面的指定地址开始写入指定个数的数据
// WriteAddr :开始写入的地址 对24c02为0~255
// pBuffer   :数据数组首地址
// NumToWrite:要写入数据的个数
void AT24CXX_Write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite)
{
     while (NumToWrite--)
     {
          i2c_24c02_write_mem_8bit(WriteAddr, *pBuffer);
          WriteAddr++;
          pBuffer++;
     }
}

// 在AT24CXX里面的指定地址开始读出指定个数的数据
// ReadAddr :开始读出的地址 对24c02为0~255
// pBuffer  :数据数组首地址
// NumToRead:要读出数据的个数
void AT24CXX_Read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead)
{
     while (NumToRead)
     {
          *pBuffer++ = i2c_24c02_read_mem_8bit(ReadAddr++);
          NumToRead--;
     }
}
